# encoding: utf-8
import datetime, requests, os, pexpect, traceback

from flask import request, send_from_directory
from app.extensions import log, db
from flask_restplus import Resource
from app.extensions.api import Namespace
from app.modules.common.utils import DbCommit, checkToken, recursive_json_loads, strToList, sendMqMessage
from app.modules.common.schemas import BaseSchema
from app.modules.common.parameters import BaseParameters
from . import parameters, schemas
from .models import IntegrationInfo, IntegrationPlan, IntegrationEditionChengeRecord as changeRecord, \
    IntegrationOnlineDesc
from app.modules.project import schemas as projectschemas
from app.modules.project.models import ProjectConfig, ProjectSql, ProjectDeployTime, ProjectSqlRecord, \
    ProjectHandOverRecord
from app.modules.projectPlan.models import ProjectPlanInfo, PlanMember
from app.modules.projectPlan.schemas import UserListSchema
from app.modules.projectPlan.parameters import ProjectPlanBaseParameters
from config import BaseConfig
from app.modules.common.dateUtil import getIntegrationCycle
from werkzeug.utils import secure_filename
from app.modules.operation.resources import addOperationRecord
from app.modules.common.jsonFileUtil import saveJsonFile, getJsonFile
from app.modules.common.beetleHttpUtil import beetlePost
from app.modules.project.common import getProListByParam, getProListByParamWithCache
from app.modules.projectPlan.common import getPlanByParam, getPlanListByParamWithCache
from .common import uploadFile, getIntegrationMembers

api = Namespace('integration', description = "集成计划")  # pylint: disable=invalid-name


@api.route('/createIntegrationPlan')
class CreateIntegrationPlan(Resource):
    @api.parameters(parameters.CreateIntegrationPlanParameters())
    @api.response(BaseSchema(many = False))
    @checkToken
    def get(self, args, **kwargs):
        """
        创建集成计划
        :param args:
        :return:
        """
        log.info("============== start create integration plan ==============")
        _year = args['year']
        _week = args['week']
        return createIntegrationByWeek(_year, _week)


def createIntegrationByWeek(_year, _week):
    _obj = getIntegrationCycle(_year, _week)
    _info = IntegrationInfo.query.filter_by(integration_year = _obj['year'], integration_cycle = _obj['week']).first()
    if _info is None:
        _info = IntegrationInfo(integration_cycle = _obj['week'],
                                integration_name = '集成计划%s第%s周' % (_obj['year'], _obj['week']),
                                integration_date = str(_obj['start']), online_date = str(_obj['end']),
                                integration_status = 'INT_NOT_START', integration_year = _obj['year'])
        db.session.add(_info)
        log.info("============== add integration plan %s ==============" % _info.integration_name)

        for _t in ProjectDeployTime.query.filter_by(integration_id = '1').all():
            _time = ProjectDeployTime(trunk_name = _t.trunk_name, zone_code = _t.zone_code,
                                      deploy_start_time = "%s %s" % (_info.online_date, _t.deploy_start_time),
                                      deploy_end_time = "%s %s" % (_info.online_date, _t.deploy_end_time),
                                      hot_deploy = _t.hot_deploy, deployer_account = _t.deployer_account,
                                      deployer_realname = _t.deployer_realname, integration_id = _info.integration_id)
            db.session.add(_time)

        return DbCommit()
    else:
        _msg = "%s年第%s周集成计划已存在" % (_year, _week)
        log.error("============== %s ==============" % _msg)
        return {'success': False, 'msg': _msg}


def createIntegration():
    log.info("============== start create integration plan method ==============")

    now = datetime.datetime.now()
    year = now.year
    week = now.strftime('%W')
    return createIntegrationByWeek(year, int(week) + 1)


@api.route('/createEmergencyIntegrationPlan')
class CreateEmergencyIntegrationPlan(Resource):
    @api.parameters(parameters.CreateEmergencyIntegrationPlanParameters())
    @api.response(BaseSchema(many = False))
    @checkToken
    def get(self, args, **kwargs):
        """
        创建紧急项目集成计划
        :param args:
        :return:
        """
        log.info("============== start create emergency integration plan ==============")
        _emergency_plan_id = args['emergency_plan_id']
        _plan = getPlanByParam(plan_id = _emergency_plan_id, isEmergency = '0')
        if _plan is None:
            _msg = "紧急项目 %s 不存在" % _emergency_plan_id
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _info = IntegrationInfo.query.filter_by(integration_name = _plan.plan_name).first()
        if _info is not None:
            _msg = "集成计划 %s 已存在" % _plan.plan_name
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}
        # 添加集成计划记录
        _i = IntegrationInfo(integration_name = str(_plan.plan_name).replace(" ", ''),
                             online_date = _plan.expect_release_date,
                             integration_status = 'INTEGRATIONING', isEmergency = '0')

        db.session.add(_i)
        # 添加发布时间记录
        for _t in ProjectDeployTime.query.filter_by(integration_id = '1').all():
            _time = ProjectDeployTime(trunk_name = _t.trunk_name, zone_code = _t.zone_code,
                                      deploy_start_time = "%s %s" % (_i.online_date, _t.deploy_start_time),
                                      deploy_end_time = "%s %s" % (_i.online_date, _t.deploy_end_time),
                                      hot_deploy = _t.hot_deploy, deployer_account = _t.deployer_account,
                                      deployer_realname = _t.deployer_realname, integration_id = _i.integration_id)
            db.session.add(_time)
        # 关联集成计划与项目
        _inplan = IntegrationPlan(_i.integration_id, _plan.plan_id)
        db.session.add(_inplan)
        _plan.plan_status = 'INTEGRATIONING'

        for _pro in getProListByParam(plan_id = _plan.plan_id):
            _pro.project_status = 'INTEGRATIONING'
        return DbCommit(cleanPro = True, cleanPlan = True)


@api.route('/getIntegrationPlanList')
class GetIntegrationPlanList(Resource):
    @api.parameters(parameters.IntegrationBaseFalseParameters())
    @api.response(schemas.IntegrationListSchema(many = False))
    @checkToken
    def get(self, args, **kwargs):
        """
        获取集成计划列表
        :param args:
        :return:
        """
        log.info("============== start get integration plan list ==============")
        _integration_id = args['integration_id']
        _integration_name = args['integration_name']
        _isEmergency = args['isEmergency']
        _hasProList = args['hasProList']

        _query = IntegrationInfo.query
        if _integration_id is not None:
            _query = _query.filter(IntegrationInfo.integration_id == _integration_id)
        if _integration_name is not None:
            _query = _query.filter(IntegrationInfo.integration_name == _integration_name)
        if _isEmergency is not None:
            _query = _query.filter(IntegrationInfo.isEmergency == _isEmergency)

        _list = _query.order_by(IntegrationInfo.online_date.desc()).all()
        for _int in _list:
            _int.members = getIntegrationMembers(_int.integration_id)
            if _hasProList:
                _int.projects = getIntegrationProjectInfoList(_int.integration_id, None, True)
        return {'success': True, 'msg': '', 'data': _list}


@api.route('/getIntegrationByPlan')
class GetIntegrationByPlan(Resource):
    @api.parameters(ProjectPlanBaseParameters())
    @api.response(schemas.IntegrationListSchema(many = False))
    @checkToken
    def get(self, args, **kwargs):
        """
        根据项目id获取集成计划信息
        :param args:
        :return:
        """
        log.info("============== start get integration by plan ==============")
        _plan_id = args['plan_id']

        _plan = getPlanByParam(plan_id = _plan_id, withCache = True)
        if _plan is None:
            _msg = "项目 %s 不存在" % _plan_id
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _ip = IntegrationPlan.query.filter_by(plan_id = _plan_id).first()
        if _ip is None:
            _msg = "项目 %s还没有集成" % _plan_id
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _list = IntegrationInfo.query.filter_by(integration_id = _ip.integration_id).all()
        if len(_list) == 0:
            _msg = "集成计划%s不存在" % _ip.integration_id
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}
        return {'success': True, 'msg': '', 'data': _list}


@api.route('/pigeonholeIntegration')
class PigeonholeIntegration(Resource):
    @api.parameters(parameters.IntegrationBaseParameters())
    @api.response(BaseSchema(many = False))
    @checkToken
    def get(self, args, **kwargs):
        """
        集成计划归档
        :param args:
        :return:
        """
        log.info("============== start pigeonhole integration plan ==============")
        _integration_name = args['integration_name']
        _integration_id = args['integration_id']
        log.info("============== integration_name is %s ==============" % _integration_name)
        log.info("============== integration_id is %s ==============" % _integration_id)
        if _integration_id is not None:
            _info = IntegrationInfo.query.filter_by(integration_id = _integration_id).first()
        else:
            _info = IntegrationInfo.query.filter_by(integration_name = _integration_name).first()
        if _info is None:
            _msg = "集成计划 %s 不存在" % _integration_name
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        addOperationRecord('ONLINE_INTEGRATION', _integration_name, None, None, 'integration online', **kwargs)

        for _plan in IntegrationPlan.query.filter_by(integration_id = _info.integration_id).all():
            _planinfo = getPlanByParam(plan_id = _plan.plan_id)
            if _planinfo is not None and _planinfo.plan_status == 'HAND_OVER':
                _planinfo.plan_status = 'ONLINE'
                log.info("send mq message to uplan.exchange . plan_id = %s" % _plan.plan_id)
                # 发送mq消息通知matrix项目上线
                sendMqMessage('uplan.exchange', {"type": "ONLINE", "map": {"plan_id": _plan.plan_id}})
                for _project in getProListByParam(plan_id = _plan.plan_id):
                    if _project is not None and _project.project_status == 'HAND_OVER':
                        _project.project_status = 'ONLINE'
                    else:
                        log.error("app.modules.integration.resources.PigeonholeIntegration %s " % _project.to_dict())
            else:
                log.error("app.modules.integration.resources.PigeonholeIntegration %s " % _planinfo.to_dict())

        _info.integration_status = 'ONLINE'

        return DbCommit(cleanPro = True, cleanPlan = True)


@api.route('/saveIntegrationInfo')
class SaveIntegrationInfo(Resource):
    @api.parameters(parameters.SaveIntegrationInfoParameters())
    @api.response(BaseSchema(many = False))
    @checkToken
    def post(self, args, **kwargs):
        """
        保存集成计划内项目及工程信息
        :param args:
        :return:
        """
        log.info("============== start save integration info ==============")
        _integration_name = args['integration_name']
        _plan_list = args['plan_list']
        _project_list = args['project_list']
        _isEmail = args['isEmail']
        _isDeloy = args['isDeloy']
        log.info("============== integration_name is %s ==============" % _integration_name)
        log.info("============== plan_list is %s ==============" % _plan_list)
        log.info("============== project_list is %s ==============" % _project_list)
        log.info("============== isEmail is %s ==============" % _isEmail)
        log.info("============== isDeloy is %s ==============" % _isDeloy)

        _plan_list = eval(str(_plan_list).replace('null', 'None'))
        if type(_plan_list) is not list:
            _msg = "this plan_list %s is not list" % _plan_list
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _project_list = eval(
            str(_project_list).replace('null', 'None').replace('true', 'True').replace('false', 'False'))
        if type(_project_list) is not list:
            _msg = "this project_list %s is not list" % _project_list
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _info = IntegrationInfo.query.filter_by(integration_name = _integration_name).first()
        if _info is None:
            _msg = "集成计划 %s 不存在" % _integration_name
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _info.integration_status = 'INTEGRATIONING'

        _planids = []
        for _plan in _plan_list:
            _p = getPlanByParam(plan_name = _plan)
            if _p is None:
                _msg = "项目 %s 不存在" % _plan
                log.error("============== %s ==============" % _msg)
                return {'success': False, 'msg': _msg}

            _inplan = IntegrationPlan(_info.integration_id, _p.plan_id)
            _planids.append(_p.plan_id)
            db.session.add(_inplan)
            _p.plan_status = 'INTEGRATIONING'
            # 项目集成中
            sendMqMessage('uplan.exchange', {"type": "INTEGRATE_PLAN", "map": {"plan_id": _p.plan_id}})

        for _pro in _project_list:
            _list = getProListByParam(plan_ids = _planids, trunk_name = _pro['trunk_name'])
            for _project in _list:
                if _project.plan_id == _pro['selectPlan']['plan_id']:
                    _project.project_status = 'INTEGRATIONING'
                else:
                    _project.project_status = 'PRO_MERGED'

        _result = DbCommit(cleanPro = True, cleanPlan = True)
        if not _result['success']:
            return _result

        # 添加agnet申请记录GET /apply_record/addIntegrationApply
        _url = "%s/apply_record/addIntegrationApply?token_id=%s&integration_id=%s&integration_name=%s&start_date=%s&expect_recover_date=%s" % (
            BaseConfig.UCLOUD_MASTER_URL, args['token_id'], _info.integration_id, _integration_name,
            _info.integration_date, _info.online_date)
        recursive_json_loads(requests.get(url = _url).content)

        return {'success': True, 'msg': ""}


@api.route('/addPlanForIntegration')
class AddPlanForIntegration(Resource):
    @api.parameters(parameters.AddPlanForIntegrationParameters())
    @api.response(BaseSchema(many = False))
    @checkToken
    def post(self, args, **kwargs):
        """
        为已经规划好的集成计划添加项目
        :param args:
        :return:
        """
        log.info("============== start add plan for integration==============")
        _integration_id = args['integration_id']
        _plan_id = args['plan_id']

        _info = IntegrationInfo.query.filter_by(integration_id = _integration_id).first()
        if _info is None:
            _msg = "集成计划 %s 不存在" % _integration_id
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _p = getPlanByParam(plan_id = _plan_id)
        if _p is None:
            _msg = "项目 %s 不存在" % _plan_id
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _inplan = IntegrationPlan(_info.integration_id, _p.plan_id)
        db.session.add(_inplan)
        _p.plan_status = 'INTEGRATIONING'

        for _pro in getProListByParam(plan_id = _plan_id):
            _pro.project_status = 'INTEGRATIONING'

        sendMqMessage('uplan.exchange', {"type": "INTEGRATE_PLAN", "map": {"plan_id": _plan_id}})
        return DbCommit(cleanPro = True, cleanPlan = True)


@api.route('/deployIntegrationPlan')
class DeployIntegrationPlan(Resource):
    @api.parameters(parameters.IntegrationBaseParameters())
    @api.response(BaseSchema(many = False))
    @checkToken
    def get(self, args, **kwargs):
        """
        自动部署集成计划内的工程
        :param args:
        :return:
        """
        log.info("============== start deploy integration project ==============")
        _integration_name = args['integration_name']
        log.info("============== integration_name is %s ==============" % _integration_name)
        _info = IntegrationInfo.query.filter_by(integration_name = _integration_name).first()
        if _info is None:
            _msg = "集成计划 %s 不存在" % _integration_name
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        # 调用集成agent发布集成计划
        # _url = "%s/project/editionInfoList?tokenId=%s&projectName=%s" % (
        #     BaseConfig.INTEGRATION_AGENT_URL)
        # _rtn = recursive_json_loads(requests.post(url = _url).content)

        return {'success': True, 'msg': ''}


@api.route('/getIntegrationProjectInfoList')
class GetIntegrationProjectInfoList(Resource):
    @api.parameters(parameters.GetIntegrationProjectInfoListParameters())
    @api.response(projectschemas.ProjectListSchema(many = False))
    @checkToken
    def get(self, args, **kwargs):
        """
        获取集成计划内所有项目内的工程信息
        :param args:
        :return:
        """
        log.info("============== start get integration project info list ==============")
        _integration_name = args['integration_name']
        _isHideMergePro = args['isHideMergePro']
        _status = args['status']
        _withEmergency = args['withEmergency']
        log.info("============== integration_name is %s ==============" % _integration_name)
        log.info("============== isHideMergePro is %s ==============" % _isHideMergePro)
        log.info("============== status is %s ==============" % _status)
        log.info("============== withEmergency is %s ==============" % _withEmergency)
        _info = IntegrationInfo.query.filter_by(integration_name = _integration_name).first()
        if _info is None:
            _msg = "集成计划 %s 不存在" % _integration_name
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}
        _list = getIntegrationProjectInfoList(_info.integration_id, _status, _isHideMergePro,
                                              withEmergency = _withEmergency)
        return {'success': True, 'msg': '', 'data': _list}


@api.route('/getIntegrationProjectListForWeek')
class GetIntegrationProjectListForWeek(Resource):
    @api.parameters(BaseParameters())
    @api.response(projectschemas.ProjectListSchema(many = False))
    @checkToken
    def get(self, args, **kwargs):
        """
        获取当前周要发布的工程列表
        :param args:
        :return:
        """
        now = datetime.datetime.now()
        year = now.year
        week = now.strftime('%W')

        _info = IntegrationInfo.query.filter_by(integration_year = year, integration_cycle = week).first()
        if _info is None:
            _msg = "%s 年第 %s 周集成计划不存在" % (year, week)
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}
        _list = getIntegrationProjectInfoList(_info.integration_id, None, True)
        return {'success': True, 'msg': '', 'data': _list}


def getIntegrationProjectInfoList(_integration_id, _status, _isHideMergePro, _trunk_name = None, withEmergency = None):
    _planlist = IntegrationPlan.query.filter_by(integration_id = _integration_id).all()

    if len(_planlist) == 0:
        return []
    _l = []
    for _plan in _planlist:
        _l.append(_plan.plan_id)

    if withEmergency is not None and withEmergency:
        for _em in IntegrationInfo.query.filter_by(isEmergency = 0).filter_by(
                integration_status = 'INTEGRATIONING').all():
            _ep = IntegrationPlan.query.filter_by(integration_id = _em.integration_id).first()
            if _ep is not None:
                _l.append(_ep.plan_id)

    _list = getProListByParamWithCache(project_status = _status, isHideMergePro = _isHideMergePro,
                                       trunk_name = _trunk_name, plan_ids = _l)
    return _list


@api.route('/getProjectPlanListByIntegration')
class GetProjectPlanListByIntegration(Resource):
    @api.parameters(parameters.IntegrationBaseParameters())
    @api.response(schemas.IntegrationPlanListSchema(many = False))
    @checkToken
    def get(self, args, **kwargs):
        """
        获取集成计划内项目列表
        :param args:
        :return:
        """
        log.info("============== start get integration's project plan list ==============")
        _integration_name = args['integration_name']
        log.info("============== integration_name is %s ==============" % _integration_name)
        _integrationInfo = IntegrationInfo.query.filter_by(integration_name = _integration_name).first()
        if _integrationInfo is None:
            _msg = "集成计划 %s 不存在" % _integration_name
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _l = IntegrationPlan.query.filter_by(integration_id = _integrationInfo.integration_id).all()
        if len(_l) == 0:
            return {'success': True, 'msg': '', 'data': []}
        _plans = []
        for _plan in _l:
            _plans.append(_plan.plan_id)

        _list = getPlanListByParamWithCache(plan_ids = _plans)
        for _info in _list:
            _row = getProListByParamWithCache(plan_id = _info.plan_id, isHideMergePro = True)
            if len(_row) == 0:
                _info.isDisable = True
            else:
                _info.isDisable = False
        return {'success': True, 'msg': '', 'data': _list}


@api.route('/disableProjectPlanInIntegration')
class DisableProjectPlanInIntegration(Resource):
    @api.parameters(parameters.DisableProjectPlanInIntegrationParameters())
    @api.response(BaseSchema(many = False))
    @checkToken
    def get(self, args, **kwargs):
        """
        撤下集成计划内项目
        :param args:
        :return:
        """
        log.info("============== start disable integration's project plan ==============")
        _integration_name = args['integration_name']
        _plan_name = args['plan_name']
        log.info("============== integration_name is %s ==============" % _integration_name)
        log.info("============== plan_name is %s ==============" % _plan_name)
        _integrationInfo = IntegrationInfo.query.filter_by(integration_name = _integration_name).first()
        if _integrationInfo is None:
            _msg = "集成计划 %s 不存在" % _integration_name
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _planInfo = getPlanByParam(plan_name = _plan_name)
        if _planInfo is None:
            _msg = "项目 %s 不存在" % _plan_name
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _info = IntegrationPlan.query.filter_by(integration_id = _integrationInfo.integration_id,
                                                plan_id = _planInfo.plan_id).first()
        if _info is None:
            _msg = "集成计划 %s 内不存在项目 %s" % (_integration_name, _plan_name)
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}
        _list = getProListByParam(plan_id = _planInfo.plan_id, isHideMergePro = True)
        if len(_list) != 0:
            _msg = "项目 %s 内存在合并后主干工程，不能撤下" % _plan_name
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _planInfo.plan_status = 'BE_CANCEL'
        for _pro in _list:
            _pro.project_status = 'BE_CANCEL'

        db.session.delete(_info)

        sendMqMessage('uplan.exchange', {"type": "CANCEL_INTEGRATE_PLAN", "map": {"plan_id": _planInfo.plan_id}})

        return DbCommit(cleanPro = True, cleanPlan = True)


@api.route('/getProjectConfig')
class GetProjectConfig(Resource):
    @api.parameters(parameters.IntegrationBaseParameters())
    @api.response(projectschemas.ProjectConfigListSchema(many = False))
    @checkToken
    def get(self, args, **kwargs):
        """
        获取集成计划内所有主干工程的配置文件修改信息列表
        :param args:
        :return:
        """
        log.info("============== start get integration's project config ==============")
        _integration_name = args['integration_name']
        log.info("============== integration_name is %s ==============" % _integration_name)
        _integrationInfo = IntegrationInfo.query.filter_by(integration_name = _integration_name).first()
        if _integrationInfo is None:
            _msg = "集成计划 %s 不存在" % _integration_name
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        # _list = ProjectConfig.query.filter_by(integration_id = _integrationInfo.integration_id).all()

        _list = []
        for config, integration_name in db.session.query(ProjectConfig, IntegrationInfo.integration_name, ).filter(
                ProjectConfig.integration_id == IntegrationInfo.integration_id).filter(
            ProjectConfig.integration_id == _integrationInfo.integration_id).all():
            config.integration_name = integration_name
            _list.append(config)

        return {'success': True, 'msg': '', 'data': _list}


@api.route('/updateProjectConfig')
class UpdateProjectConfig(Resource):
    @api.parameters(parameters.UpdateProjectConfigParameters())
    @api.response(BaseSchema(many = False))
    @checkToken
    def post(self, args, **kwargs):
        """
        修改工程的配置信息
        :param args:
        :return:
        """
        log.info("============== start update integration's project config ==============")
        _integration_name = args['integration_name']
        _config_list = args['config_list']
        log.info("============== integration_name is %s ==============" % _integration_name)
        log.info("============== config_list is %s ==============" % _config_list)
        _integrationInfo = IntegrationInfo.query.filter_by(integration_name = _integration_name).first()
        if _integrationInfo is None:
            _msg = "集成计划 %s 不存在" % _integration_name
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _config_list = eval(str(_config_list).replace('null', 'None'))
        if type(_config_list) is not list:
            _msg = "this project_list %s is not list" % _config_list
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        for _config in _config_list:
            if _config['isDel'] == '0':
                _c = ProjectConfig.query.filter_by(integration_id = _integrationInfo.integration_id,
                                                   trunk_name = _config['trunk_name'], key = _config['key']).first()
                if _c is None:
                    _info = ProjectConfig(integration_id = _integrationInfo.integration_id,
                                          trunk_name = _config['trunk_name'], key = _config['key'],
                                          value = _config['value'], desc = _config['desc'], type = _config['type'],
                                          is_ops_check = _config['is_ops_check'], file_name = _config['file_name'],
                                          config_type = _config['config_type'], value_from = _config['value_from'])
                    db.session.add(_info)
                else:
                    _c.value = _config['value']
                    _c.desc = _config['desc']
                    _c.type = _config['type']
                    _c.is_ops_check = _config['is_ops_check']
                    _c.file_name = _config['file_name']
                    _c.config_type = _config['config_type']
                    _c.value_from = _config['value_from']
            elif _config['isDel'] == '1':
                _c = ProjectConfig.query.filter_by(integration_id = _integrationInfo.integration_id,
                                                   trunk_name = _config['trunk_name'], key = _config['key']).first()
                if _c is not None:
                    db.session.delete(_c)
        return DbCommit()


@api.route('/getDrawSqlRecord')
class GetDrawSqlRecord(Resource):
    @api.parameters(parameters.IntegrationBaseParameters())
    @api.response(projectschemas.ProjectSqlRecordListSchema(many = False))
    @checkToken
    def get(self, args, **kwargs):
        """
        获取集成计划抽取sql记录
        :param args:
        :return:
        """
        log.info("============== start get integration's project sql list ==============")
        _integration_name = args['integration_name']
        log.info("============== integration_name is %s ==============" % _integration_name)
        _integrationInfo = IntegrationInfo.query.filter_by(integration_name = _integration_name).first()
        if _integrationInfo is None:
            _msg = "集成计划 %s 不存在" % _integration_name
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _list = ProjectSqlRecord.query.filter_by(integration_id = _integrationInfo.integration_id).order_by(
            ProjectSqlRecord.draw_time.desc()).all()
        return {'success': True, 'msg': '', 'data': _list}


@api.route('/getProjectSql')
class GetProjectSql(Resource):
    @api.parameters(parameters.IntegrationBaseParameters())
    @api.response(projectschemas.ProjectSqlListSchema(many = False))
    @checkToken
    def get(self, args, **kwargs):
        """
        获取集成计划内所有主干工程的sql文件列表
        :param args:
        :return:
        """
        log.info("============== start get integration's project sql list ==============")
        _integration_name = args['integration_name']
        log.info("============== integration_name is %s ==============" % _integration_name)
        _integrationInfo = IntegrationInfo.query.filter_by(integration_name = _integration_name).first()
        if _integrationInfo is None:
            _msg = "集成计划 %s 不存在" % _integration_name
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _list = []
        for sql, integration_name in db.session.query(ProjectSql, IntegrationInfo.integration_name, ).filter(
                ProjectSql.integration_id == IntegrationInfo.integration_id).filter(
            ProjectSql.integration_id == _integrationInfo.integration_id).all():
            sql.integration_name = integration_name
            sql.analyse = analyseSql(sql.file_path)
            _list.append(sql)

        return {'success': True, 'msg': '', 'data': _list}


def analyseSql(file_path):
    _rtn = []
    _sh = '/bin/bash -c "cat %s | grep -En \'(ALTER|alter)\s+(TABLE|table)\s\'"' % file_path
    output, status = pexpect.run(_sh, withexitstatus = 1, timeout = 60)
    try:
        if status == 0:
            _list = str(output).split('\r\n')
            for _row in _list:
                if _row != '':
                    _rtn.append({'row_num': str(_row).split(':')[0], 'row': str(_row).split(':')[1].replace('\r', '')})
        else:
            log.error('app.modules.integration.resources.analyseSql error sh:%s,output:%s' % (_sh, output))
    except BaseException:
        log.error(traceback.format_exc())
    return _rtn


@api.route('/autoDrawSqlFromProject')
class AutoDrawSqlFromProject(Resource):
    @api.parameters(parameters.IntegrationBaseParameters())
    @api.response(BaseSchema(many = False))
    @checkToken
    def get(self, args, **kwargs):
        """
        自动抽取工程内的sql文件
        :param args:
        :return:
        """
        log.info("============== start auto draw integration's project sql ==============")
        _integration_name = args['integration_name']
        log.info("============== integration_name is %s ==============" % _integration_name)
        _info = IntegrationInfo.query.filter_by(integration_name = _integration_name).first()
        if _info is None:
            _msg = "集成计划 %s 不存在" % _integration_name
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _plans = IntegrationPlan.query.filter_by(integration_id = _info.integration_id).all()
        if _plans is None or len(_plans) == 0:
            _msg = "集成计划 %s 还没有集成项目" % _integration_name
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _l = []
        for _plan in _plans:
            _l.append(_plan.plan_id)

        _list = []
        _status = {}
        _pros = []

        for _pro in getProListByParamWithCache(plan_ids = _l, isHideMergePro = True, isOnBeetle = "0",
                                               not_contain_package_type = 'maven_jar'):
            _list.append(str(_pro.project_name))
            _st = {'name': str(_pro.project_name)}
            _pros.append(_st)

        if _list is None or len(_list) == 0:
            _msg = "集成计划 %s 没有工程" % _integration_name
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _status['status'] = 'running'  # 抽取中
        _status['desc'] = None
        _status['projects'] = _pros
        _status['date'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        saveJsonFile(getAutoDrawSqlStatusFilePath(_info.integration_id), _status)
        if _info.isEmergency == "0":
            _path = '%s/sql/%s' % (BaseConfig.BEETLE_BASE_PATH, _info.integration_id)
        else:
            _path = '%s/sql/%s-%s' % (BaseConfig.BEETLE_BASE_PATH, _info.integration_year, _info.integration_cycle)

        _url = "%s/projectREST/autoDrawSql?tokenId=%s&dir=%s&integrationId=%s&list=%s " % (
            BaseConfig.BEETLE_API_URL, args['token_id'], _path, _info.integration_id, str(_list))
        _rtn = recursive_json_loads(requests.post(url = _url).content)

        if _rtn.code != 0:
            _msg = "抽取集成计划 %s 工程sql文件失败. desc:%s" % (_integration_name, _rtn.desc)
            log.error("============== %s ==============" % _msg)
            _status['status'] = 'error'  # 抽取失败
            _status['desc'] = _rtn.desc
            _status['date'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            saveJsonFile(getAutoDrawSqlStatusFilePath(_info.integration_id), _status)
            return {'success': False, 'msg': _msg}

        return {'success': True, 'msg': '调用后台抽取sql文件成功,请稍后查询抽取状态'}


@api.route('/getAutoDrawSqlStatus')
class GetAutoDrawSqlStatus(Resource):
    @api.parameters(parameters.IntegrationIdBaseParameters())
    @api.response(schemas.AutoDrawSqlStatusSchema(many = False))
    @checkToken
    def get(self, args, **kwargs):
        """
        获取后台抽取sql的状态
        :param args:
        :return:
        """
        log.info("============== start get auto draw sql status  ==============")
        _integration_id = args['integration_id']

        _status = getJsonFile(getAutoDrawSqlStatusFilePath(_integration_id))

        return {'success': True, 'msg': '', 'data': _status}


@api.route('/saveProjectSqlInfo')
class SaveProjectSqlInfo(Resource):
    @api.parameters(parameters.saveProjectSqlInfoParameters())
    @api.response(BaseSchema(many = False))
    def post(self, args, **kwargs):
        """
        后台抽取工程内的sql文件成功后,回调保存信息
        :param args:
        :return:
        """
        log.info("============== start save project sql info ==============")
        _integration_id = args['integration_id']
        _list = strToList(args['list'])
        log.info("============== integration_id is %s ==============" % _integration_id)
        log.info("============== list is %s ==============" % _list)

        _status = getJsonFile(getAutoDrawSqlStatusFilePath(_integration_id))

        if type(_list) is not list:
            _msg = "this list %s is not list" % _list
            log.error("============== %s ==============" % _msg)
            _status['status'] = 'error'  # 抽取失败
            _status['desc'] = _msg
            _status['date'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            saveJsonFile(getAutoDrawSqlStatusFilePath(_integration_id), _status)
            return {'success': False, 'msg': _msg}

        _status['projects'] = _list

        _now = datetime.datetime.now()
        for _project in _list:
            db.session.execute(
                "DELETE from project_sql where integration_id = :_integration_id AND trunk_name = :_trunk_name",
                {'_integration_id': _integration_id, '_trunk_name': str(_project['project']).split('_')[0]})

            db.session.add(
                ProjectSqlRecord(project_name = _project['project'], integration_id = _integration_id,
                                 trunk_name = str(_project['project']).split('_')[0], status = _project['status'],
                                 change_desc = _project['change_desc'], draw_time = _now))
            if _project['status']:
                for _s in _project['sqls']:
                    _sql = ProjectSql(project_name = _project['project'], integration_id = _s['integration_id'],
                                      trunk_name = _s['trunk_name'], file_name = _s['file_name'],
                                      file_path = _s['file_path'], file_size = _s['file_size'], draw_time = _now,
                                      modify_date = _s['modify_date'], file_modify_date = _s['file_modify_date'],
                                      md5 = _s['md5'])
                    db.session.add(_sql)

        _result = DbCommit()
        if not _result['success']:
            _status['status'] = 'error'  # 抽取失败
            _status['desc'] = _result['msg']
            _status['date'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            saveJsonFile(getAutoDrawSqlStatusFilePath(_integration_id), _status)
            return _result

        _status['status'] = 'success'
        _status['desc'] = None
        _status['date'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        saveJsonFile(getAutoDrawSqlStatusFilePath(_integration_id), _status)

        return _result


@api.route('/uploadSqlFromProject')
class UploadSqlFromProject(Resource):
    @api.parameters(parameters.sqlUploadParameters())
    @api.response(BaseSchema(many = False))
    @checkToken
    def post(self, args, **kwargs):
        """
        sql文件上传
        :param args:
        :return:
        """
        log.info("============== start upload integration's project sql ==============")
        _integration_name = args['integration_name']
        _project_name = args['project_name']
        _dir = args['dir']

        _info = IntegrationInfo.query.filter_by(integration_name = _integration_name).first()
        if _info is None:
            _msg = "集成计划 %s 不存在" % _integration_name
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        f = request.files['file']
        fname = secure_filename(f.filename)
        _path = '%s/sql/%s-%s/%s' % (
            BaseConfig.BEETLE_BASE_PATH, _info.integration_year, _info.integration_cycle,
            str(_project_name).split("_")[0])

        if _dir is not None:
            fname = '%s_%s' % (str(_dir).replace('/', '_'), fname)
            _path = '%s/%s' % (_path, _dir)

        log.info("============== fname is %s ==============" % fname)

        _file_path = uploadFile(_path, fname, f)

        db.session.execute(
            "DELETE from project_sql where integration_id = :_integration_id AND project_name = :_project_name AND file_name = :_file_name",
            {'_integration_id': _info.integration_id, '_project_name': _project_name, '_file_name': fname})

        _sql = ProjectSql(project_name = _project_name, integration_id = _info.integration_id,
                          trunk_name = str(_project_name).split("_")[0], file_name = fname,
                          file_path = _file_path, is_upload = "0")
        db.session.add(_sql)
        return DbCommit()


@api.route('/removeSqlFile')
class RemoveSqlFile(Resource):
    @api.parameters(parameters.sqlDownloadParameters())
    @api.response(BaseSchema(many = False))
    @checkToken
    def get(self, args, **kwargs):
        """
        删除sql文件
        :param args:
        :return:
        """
        log.info("============== start remove project sql ==============")
        _integration_name = args['integration_name']
        _trunk_name = args['trunk_name']
        _filename = args['filename']
        log.info("============== integration_name is %s ==============" % _integration_name)
        log.info("============== trunk_name is %s ==============" % _trunk_name)
        log.info("============== filename is %s ==============" % _filename)
        _info = IntegrationInfo.query.filter_by(integration_name = _integration_name).first()
        if _info is None:
            _msg = "集成计划 %s 不存在" % _integration_name
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _sql = ProjectSql.query.filter_by(integration_id = _info.integration_id, trunk_name = _trunk_name,
                                          file_name = _filename).first()
        if _sql is not None:
            if os.path.exists(_sql.file_path):
                os.remove(_sql.file_path)
            db.session.delete(_sql)
            return DbCommit()

        return {'success': True, 'msg': ''}


@api.route('/downloadFile')
class DownloadFile(Resource):
    @api.parameters(parameters.DownloadFileParameters())
    @checkToken
    def get(self, args, **kwargs):
        """
        文件下载
        :param args:
        :return:
        """
        _file_name = args['file_name']
        _file_path = args['file_path']

        if not os.path.exists(_file_path):
            _msg = "文件%s不存在" % _file_path
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        return send_from_directory(str(_file_path).replace('/%s' % _file_name, ''), _file_name, as_attachment = True)


@api.route('/downloadSqlPackage')
class DownloadSqlPackage(Resource):
    @api.parameters(parameters.IntegrationBaseParameters())
    @checkToken
    def get(self, args, **kwargs):
        """
        打包下载集成计划内的所有sql文件
        :param args:
        :return:
        """
        log.info("============== start download integration's project sql package ==============")
        _integration_name = args['integration_name']
        log.info("============== integration_name is %s ==============" % _integration_name)
        _info = IntegrationInfo.query.filter_by(integration_name = _integration_name).first()
        if _info is None:
            _msg = "集成计划 %s 不存在" % _integration_name
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        if _info.isEmergency == "0":
            _name = '%s' % _info.integration_id
        else:
            _name = '%s-%s' % (_info.integration_year, _info.integration_cycle)

        _sh = '/bin/bash -c "source /etc/profile && cd %s/sql && rm -rf %s.tgz && tar -zcf %s.tgz %s/ "' % (
            BaseConfig.BEETLE_BASE_PATH, _name, _name, _name)
        output, status = pexpect.run(_sh, withexitstatus = 1, timeout = 60)
        if status == 0:
            _path = '%s/sql' % BaseConfig.BEETLE_BASE_PATH
            return send_from_directory(_path, '%s.tgz' % _name, as_attachment = True)
        else:
            _msg = "打包sql文件异常. %s" % output
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}


@api.route('/checkSql')
class CheckSql(Resource):
    @api.parameters(parameters.checkProjectSqlParameters())
    @api.response(BaseSchema(many = False))
    @checkToken
    def get(self, args, **kwargs):
        """
        dba修改sql文件检查状态
        :param args:
        :return:
        """
        log.info("============== start update sql status ==============")
        _integration_id = args['integration_id']
        _trunk_name = args['trunk_name']
        _file_name = args['file_name']
        _status = args['status']
        log.info("============== integration_id is %s ==============" % _integration_id)
        log.info("============== trunk_name is %s ==============" % _trunk_name)
        log.info("============== file_name is %s ==============" % _file_name)
        log.info("============== status is %s ==============" % _status)
        _info = IntegrationInfo.query.filter_by(integration_id = _integration_id).first()
        if _info is None:
            _msg = "集成计划 %s 不存在" % _integration_id
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _sql = ProjectSql.query.filter_by(integration_id = _integration_id, trunk_name = _trunk_name,
                                          file_name = _file_name).first()
        if _sql is None:
            _msg = "文件 %s 不存在" % _file_name
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}
        _sql.is_dba_check = _status
        return DbCommit()


@api.route('/handOverIntegration')
class HandOverIntegration(Resource):
    @api.parameters(parameters.IntegrationIdBaseParameters())
    @api.response(BaseSchema(many = False))
    @checkToken
    def get(self, args, **kwargs):
        """
        集成计划交付运维
        :param args:
        :return:
        """
        log.info("============== start hand over integration ==============")
        _integration_id = args['integration_id']
        log.info("============== integration_id is %s ==============" % _integration_id)
        _info = IntegrationInfo.query.filter_by(integration_id = _integration_id).first()
        if _info is None:
            _msg = "集成计划 %s 不存在" % _integration_id
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        addOperationRecord('HAND_OVER_INTEGRATION', _integration_id, None, None, 'hand over integration', **kwargs)

        for _plan in IntegrationPlan.query.filter_by(integration_id = _info.integration_id).all():
            _planinfo = getPlanByParam(plan_id = _plan.plan_id)
            if _planinfo is not None and _planinfo.plan_status == 'INTEGRATIONING':
                _planinfo.plan_status = 'HAND_OVER'
                for _project in getProListByParam(plan_id = _plan.plan_id):
                    if _project is not None and _project.project_status == 'INTEGRATIONING':
                        _project.project_status = 'HAND_OVER'
                    else:
                        log.error("app.modules.integration.resources.HandOverIntegration %s " % _project.to_dict())
            else:
                log.error("app.modules.integration.resources.HandOverIntegration %s " % _planinfo.to_dict())

        _info.integration_status = 'HAND_OVER'
        return DbCommit(cleanPro = True, cleanPlan = True)


@api.route('/getIntegrationEditionChangeRecord')
class GetIntegrationEditionChangeRecord(Resource):
    @api.parameters(parameters.IntegrationBaseParameters())
    @api.response(schemas.EditionChangeRecordListSchema(many = False))
    @checkToken
    def get(self, args, **kwargs):
        """
        查询集成计划交付后版本更新列表
        :param args:
        :return:
        """
        log.info("============== start get integration edition change record ==============")
        _integration_name = args['integration_name']
        log.info("============== integration_name is %s ==============" % _integration_name)
        _info = IntegrationInfo.query.filter_by(integration_name = _integration_name).first()
        if _info is None:
            _msg = "集成计划 %s 不存在" % _integration_name
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}
        _list = []
        for record, integration_name, plan_name in db.session.query(changeRecord, IntegrationInfo.integration_name,
                                                                    ProjectPlanInfo.plan_name).filter(
            changeRecord.integration_id == IntegrationInfo.integration_id).filter(
            changeRecord.plan_id == ProjectPlanInfo.plan_id).filter(
            changeRecord.integration_id == _info.integration_id).order_by(
            changeRecord.create_date.desc()).all():
            record.integration_name = integration_name
            record.plan_name = plan_name
            _list.append(record)

        return {'success': True, 'msg': '', 'data': _list}


@api.route('/reIntegration')
class ReIntegration(Resource):
    @api.parameters(parameters.IntegrationIdBaseParameters())
    @api.response(BaseSchema(many = False))
    @checkToken
    def get(self, args, **kwargs):
        """
        重新规划集成计划
        :param args:
        :return:
        """
        _integration_id = args['integration_id']
        _info = IntegrationInfo.query.filter_by(integration_id = _integration_id).first()
        if _info is None:
            _msg = "集成计划 %s 不存在" % _integration_id
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        addOperationRecord('RE_INTEGRATION', _info.integration_name, _info.integration_status, None, '重新规划', **kwargs)

        if _info.integration_status == 'ONLINE':
            _msg = "集成计划 %s 已上线，不能重新规划" % _info.integration_name
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        for _IP in IntegrationPlan.query.filter_by(integration_id = _integration_id).all():
            db.session.delete(_IP)
            _plan = getPlanByParam(plan_id = _IP.plan_id)
            if _plan is not None:
                sendMqMessage('uplan.exchange', {"type": "CANCEL_INTEGRATE_PLAN", "map": {"plan_id": _plan.plan_id}})
                _plan.plan_status = 'TO_INTEGRATION'
                for _pro in getProListByParam(plan_id = _IP.plan_id):
                    _pro.project_status = 'TO_INTEGRATION'

        _info.integration_status = 'INT_NOT_START'

        db.session.execute(
            "DELETE from project_sql where integration_id = :_integration_id", {'_integration_id': _integration_id})
        db.session.execute(
            "DELETE from project_sql_record where integration_id = :_integration_id",
            {'_integration_id': _integration_id})
        db.session.execute(
            "DELETE from project_config where integration_id = :_integration_id", {'_integration_id': _integration_id})
        db.session.execute(
            "DELETE from integration_online_desc where integration_id = :_integration_id",
            {'_integration_id': _integration_id})
        # 删除抽取的sql文件
        _path = '%s/sql/%s-%s' % (BaseConfig.BEETLE_BASE_PATH, _info.integration_year, _info.integration_cycle)
        _sh = '/bin/bash -c "rm -rf %s*"' % _path
        pexpect.run(_sh, withexitstatus = 1, timeout = 60)
        # 删除抽取sql状态文件
        _sh = '/bin/bash -c "rm -rf %s/sql/status/%s"' % (BaseConfig.BEETLE_BASE_PATH, _integration_id)
        pexpect.run(_sh, withexitstatus = 1, timeout = 60)
        # 删除上传备注文件
        _sh = '/bin/bash -c "rm -rf %s/onlineDesc/%s-%s"' % (
            BaseConfig.BEETLE_BASE_PATH, _info.integration_year, _info.integration_cycle)
        pexpect.run(_sh, withexitstatus = 1, timeout = 60)

        _url = "%s/apply_record/recoverAgentForIntegration?token_id=%s&integration_id=%s" % (
            BaseConfig.UCLOUD_MASTER_URL, args['token_id'], _info.integration_id)
        recursive_json_loads(requests.get(url = _url).content)

        return DbCommit(cleanPro = True, cleanPlan = True)


@api.route('/getIntegrationMembers')
class GetIntegrationMembers(Resource):
    @api.parameters(parameters.IntegrationIdBaseParameters())
    @api.response(UserListSchema(many = False))
    @checkToken
    def get(self, args, **kwargs):
        """
        获取集成计划内所有项目的成员列表
        :param args:
        :return:
        """
        _integration_id = args['integration_id']
        _info = IntegrationInfo.query.filter_by(integration_id = _integration_id).first()
        if _info is None:
            _msg = "集成计划 %s 不存在" % _integration_id
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _list = getIntegrationMembers(_integration_id)
        return {'success': True, 'msg': '', 'data': _list}


@api.route('/getIntegrationProjectEditionList')
class GetIntegrationProjectEditionList(Resource):
    @api.parameters(parameters.IntegrationIdBaseParameters())
    @api.response(projectschemas.ProjectOnlineVersionListSchema(many = False))
    @checkToken
    def get(self, args, **kwargs):
        """
        agent发布集成环境,获取工程项目版本
        :param args:
        :return:
        """
        log.info("============== start get integration project edition list ==============")
        _integration_id = args['integration_id']

        _info = IntegrationInfo.query.filter_by(integration_id = _integration_id).first()
        if _info is None:
            _msg = "集成计划 %s 不存在" % _integration_id
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _list = []
        for pro in getIntegrationProjectInfoList(_integration_id, None, True):
            _list.append(str(pro.project_name))

        _param = {
            'apps': str(_list),
            'type': 'plan'
        }
        _rtn = beetlePost(args['token_id'], '/uCloud/getProjectReleaseVersions', _param)
        if _rtn.code != 0:
            _msg = "agent集成环境发布,获取工程项目版本失败,error:%s" % _rtn.desc
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        return {'success': True, 'msg': '', 'data': _rtn.data}


def getAutoDrawSqlStatusFilePath(_integration_id):
    _dir = '%s%s' % (BaseConfig.DRAW_SQL_STATUS_FILE, _integration_id)
    if not os.path.exists(_dir):
        os.makedirs(_dir)
    return '%s/status.json' % _dir


@api.route('/getIntegrationOnlineDesc')
class GetIntegrationOnlineDesc(Resource):
    @api.parameters(parameters.IntegrationIdBaseParameters())
    @api.response(schemas.IntegrationOnlineDescListSchema(many = False))
    @checkToken
    def get(self, args, **kwargs):
        """
        根据集成计划id获取集成计划上线描述信息
        :param args:
        :return:
        """
        log.info("============== start get integration online desc ==============")
        _integration_id = args['integration_id']

        _info = IntegrationInfo.query.filter_by(integration_id = _integration_id).first()
        if _info is None:
            _msg = "集成计划 %s 不存在" % _integration_id
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _list = IntegrationOnlineDesc.query.filter_by(integration_id = _integration_id).order_by(
            IntegrationOnlineDesc.index).all()

        return {'success': True, 'msg': '', 'data': _list}


@api.route('/saveIntegrationOnlineDesc')
class SaveIntegrationOnlineDesc(Resource):
    @api.parameters(parameters.SaveIntegrationOnlineDescParameters())
    @api.response(BaseSchema(many = False))
    @checkToken
    def post(self, args, **kwargs):
        """
        保存集成计划的上线描述信息
        :param args:
        :return:
        """
        log.info("============== start save integration desc ==============")
        _integration_id = args['integration_id']
        _desc_id = args['desc_id']
        _desc = args['desc']

        _info = IntegrationInfo.query.filter_by(integration_id = _integration_id).first()
        if _info is None:
            _msg = "集成计划 %s 不存在" % _integration_id
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}
        # 1.desc_id 不存在时  为集成计划新增描述
        if _desc_id is None:
            _desc_info = IntegrationOnlineDesc.query.filter_by(integration_id = _integration_id).order_by(
                IntegrationOnlineDesc.index.desc()).first()
            _index = 1
            # 该集成计划没有添加描述
            if _desc_info is not None:
                _index = int(_desc_info.index) + 1
            db.session.add(
                IntegrationOnlineDesc(integration_id = _integration_id, user_id = kwargs['login_user_id'],
                                      real_name = kwargs['login_user_name'], desc = _desc, index = _index))
        # 2.desc_id 存在时  修改记录
        else:
            _desc_info = IntegrationOnlineDesc.query.filter_by(integration_id = _integration_id, id = _desc_id).first()
            if _desc_info is None:
                _msg = "集成计划 %s 下没有%s该描述记录" % (_integration_id, _desc_id)
                log.error("============== %s ==============" % _msg)
                return {'success': False, 'msg': _msg}

            _desc_info.update_date = datetime.datetime.now()
            _desc_info.desc = _desc
            _desc_info.user_id = kwargs['login_user_id']
            _desc_info.real_name = kwargs['login_user_name']

        return DbCommit()


@api.route('/uploadOnlineDescFile')
class UploadOnlineDescFile(Resource):
    @api.parameters(parameters.UploadOnlineDescFileParameters())
    @api.response(BaseSchema(many = False))
    @checkToken
    def post(self, args, **kwargs):
        """
        上传上线备注文件
        :param args:
        :return:
        """
        _integration_name = args['integration_name']
        _desc_id = args['desc_id']

        _info = IntegrationInfo.query.filter_by(integration_name = _integration_name).first()
        if _info is None:
            _msg = "集成计划 %s 不存在" % _integration_name
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _desc = IntegrationOnlineDesc.query.filter_by(id = _desc_id).first()
        if _desc is None:
            _msg = "上线备注 %s 不存在" % _desc_id
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        f = request.files['file']
        fname = secure_filename(f.filename)
        _path = '%s/onlineDesc/%s-%s/%s' % (
            BaseConfig.BEETLE_BASE_PATH, _info.integration_year, _info.integration_cycle, _desc_id)

        log.info("============== fname is %s ==============" % fname)

        _file_path = uploadFile(_path, fname, f)
        _desc.file_name = fname
        _desc.file_path = _file_path

        return DbCommit()


@api.route('/removeOnlineDescFile')
class RemoveOnlineDescFile(Resource):
    @api.parameters(parameters.UploadOnlineDescFileParameters())
    @api.response(BaseSchema(many = False))
    @checkToken
    def get(self, args, **kwargs):
        """
        删除上线备注文件
        :param args:
        :return:
        """
        _integration_name = args['integration_name']
        _desc_id = args['desc_id']

        _info = IntegrationInfo.query.filter_by(integration_name = _integration_name).first()
        if _info is None:
            _msg = "集成计划 %s 不存在" % _integration_name
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _desc = IntegrationOnlineDesc.query.filter_by(id = _desc_id).first()
        if _desc is None:
            _msg = "上线备注 %s 不存在" % _desc_id
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        if _desc.file_path is None:
            _msg = "上线备注 %s 没有文件" % _desc_id
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        if os.path.exists(_desc.file_path):
            os.remove(_desc.file_path)
        _desc.file_name = None
        _desc.file_path = None
        return DbCommit()


@api.route('/getIntegrationPHORecord')
class GetIntegrationPHORecord(Resource):
    @api.parameters(parameters.IntegrationBaseParameters())
    @api.response(projectschemas.ProjectHandOverRecordListSchema(many = False))
    @checkToken
    def get(self, args, **kwargs):
        """
        根据集成计划获取工程转测记录
        :param args:
        :return:
        """
        _integration_name = args['integration_name']

        _info = IntegrationInfo.query.filter_by(integration_name = _integration_name).first()
        if _info is None:
            _msg = "集成计划 %s 不存在" % _integration_name
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _l = []
        for _pro in getIntegrationProjectInfoList(_info.integration_id, None, True):
            _l.append(_pro.project_name)

        _list = ProjectHandOverRecord.query.filter_by(type = 'INTEGRATION').filter(
            ProjectHandOverRecord.project_name.in_(_l)).order_by(ProjectHandOverRecord.create_date.desc()).all()

        return {'success': True, 'msg': '', 'data': _list}
